Skip to content

feat: support absolute pixel height in lineHeight option#5848

Open
yiliang114 wants to merge 1 commit intoxtermjs:masterfrom
yiliang114:feat/2612-lineheight-px
Open

feat: support absolute pixel height in lineHeight option#5848
yiliang114 wants to merge 1 commit intoxtermjs:masterfrom
yiliang114:feat/2612-lineheight-px

Conversation

@yiliang114
Copy link
Copy Markdown

@yiliang114 yiliang114 commented Apr 28, 2026

Summary

Closes #2612

Follow the Monaco editor convention for lineHeight interpretation:

  • Value < 8: treated as a multiplier of the character height (e.g. 1.2) — existing behavior, fully backwards compatible
  • Value >= 8: treated as an absolute pixel height (e.g. 20 means 20px)

This was suggested by @Tyriar to align with Monaco editor's approach. Compared to the string-based '23px' approach in #5730, this keeps the type signature as number (no breaking change) and provides a simpler API.

Changes

  • typings/xterm.d.ts: Updated JSDoc to document both modes
  • src/common/services/OptionsService.ts: Separated lineHeight validation from tabStopWidth with documenting comments
  • src/browser/renderer/dom/DomRenderer.ts: Cell height calculation branches on >= 8 for pixel mode, with Math.max clamp to ensure cell height never falls below character height
  • addons/addon-webgl/src/WebglRenderer.ts: Same logic; also fixed char.top centering to compare actual dimensions instead of checking lineHeight === 1
  • src/common/services/OptionsService.test.ts: Added 6 test cases covering multiplier mode, pixel mode, boundary values, and error handling

Test Results

Unit Tests

  • npm run test-unit — ✅ 2263 passing, 0 failing
  • npm run build — ✅ pass
  • npm run lint — ✅ 0 warnings

Manual Verification (DOM Renderer)

Case lineHeight Mode Expected cellHeight Actual cellHeight Status
Default 1.0 multiplier 18 (= charHeight) 18
Multiplier 1.5 multiplier 27 (= floor(18×1.5)) 27
Pixel 20 pixel 20 20
Pixel large 30 pixel 30 30
Boundary clamp 8 pixel 18 (clamp to charHeight) 18
Boundary multiplier 7.9 multiplier 142 (= floor(18×7.9)) 142
Regression 1.0 multiplier 18 18

Manual Verification (WebGL Renderer)

Case lineHeight Mode Expected cellHeight Actual cellHeight Status
WebGL pixel 25 pixel 25 25
WebGL multiplier 1.5 multiplier 27 27

Screenshots

Default (lineHeight=1.0):
01-default-lineheight-1 0

placeholder for 01-default-lineheight-1.0.png

Multiplier mode (lineHeight=1.5):
02-lineheight-1 5-multiplier

placeholder for 02-lineheight-1.5-multiplier.png

Pixel mode (lineHeight=20):
03-lineheight-20-pixel

placeholder for 03-lineheight-20-pixel.png

Pixel mode (lineHeight=30):
04-lineheight-30-pixel

placeholder for 04-lineheight-30-pixel.png

WebGL pixel mode (lineHeight=25):
08-webgl-lineheight-25-pixel

placeholder for 08-webgl-lineheight-25-pixel.png
09-webgl-lineheight-1 5-multiplier

Example usage

// Existing multiplier (unchanged)
terminal.options.lineHeight = 1.2;

// New: absolute pixel height
terminal.options.lineHeight = 23;

Follow the Monaco editor convention: when lineHeight is less than 8,
treat it as a multiplier of the character height (existing behavior);
when it is 8 or greater, treat it as an absolute pixel height.

This allows users to set an exact pixel line height (e.g. `lineHeight: 23`)
without needing to calculate the equivalent multiplier, which varies with
font size, font family, and device pixel ratio.

Fixes xtermjs#2612
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support 'px' format in lineHeight option

1 participant